//
//  HRBubbleView.m
//  MATools
//
//  Created by mazb on 2021/9/3.
//

#import "HRBubbleView.h"

#define k_BOUNDYR_MARGIN  (20.0)//横向边距
//#define kY_BOUNDYR_MARGIN //纵向向边距

typedef struct HRArrowTriangle
{
    CGPoint top, left, right;
} HRArrowTriangle;

const HRArrowTriangle HRArrowTriangleZero = {{0, 0}, {0, 0}, {0, 0}};


@interface HRBubbleView()

///气泡背景色
@property(nonatomic, strong) UIColor *color;
///气泡圆角
@property(nonatomic, assign) CGFloat radius;

///关闭按钮 默认显示
@property(nonatomic, assign) BOOL showCloseButton;
@property(nonatomic, strong) UIButton *closeButton;

///文本设置
@property(nonatomic, copy) NSString *text;
@property(nonatomic, strong) UIFont *font;
@property(nonatomic, strong) UIColor *textColor;
@property(nonatomic, assign) UIEdgeInsets textEdgeInsets;

///箭头设置
/// arrowSize.width 箭头底边宽 |  arrowSize.height 箭头底边到箭头顶端的垂直高度
@property(nonatomic, assign) CGSize arrowSize;
@property(nonatomic, assign) HRBubbleArrowOrientation arrowOrientation;

///转换后箭头三角形坐标
@property(nonatomic, assign) HRArrowTriangle arrowTriangle;
///气泡矩形部分的 rect
@property(nonatomic, assign) CGRect bubbleRect;
///文本绘制的 rect
@property(nonatomic, assign) CGRect textRect;



@end

@implementation HRBubbleView


+ (HRBubbleView *)showText:(NSString *)text
                    inView:(UIView *)relateView
                 orientation:(HRBubbleArrowOrientation)orientation
                  arrowPoint:(CGPoint)arrowPoint
                   showClose:(BOOL)showClose
{
    HRBubbleView *bubble = [[HRBubbleView alloc] init];
    bubble.showCloseButton = showClose;
    bubble.arrowOrientation = orientation;
    bubble.text = text;
    
    if (! relateView) {
        relateView = [HRBubbleView hr_appWindow];
    }
    
    CGPoint relatePoint = CGPointZero;
    CGSize superSize = relateView.bounds.size;
    CGFloat sizeMaxWidth = relateView.bounds.size.width - (bubble.textEdgeInsets.left + bubble.textEdgeInsets.right);
    CGFloat sizeMaxHeight = relateView.bounds.size.height - (bubble.textEdgeInsets.top + bubble.textEdgeInsets.bottom);
    
    CGRect bubbleRect = bubble.bubbleRect;
    switch (orientation) {
        case HRBubbleArrorLeft:
        {
            sizeMaxWidth = relateView.bounds.size.width-arrowPoint.x - bubble.arrowSize.height-k_BOUNDYR_MARGIN - (bubble.textEdgeInsets.left+bubble.textEdgeInsets.right);
            sizeMaxHeight = relateView.bounds.size.height - k_BOUNDYR_MARGIN*2-(bubble.textEdgeInsets.top + bubble.textEdgeInsets.bottom);
        }
            break;
        case HRBubbleArrorRight:
        {
            sizeMaxWidth = arrowPoint.x-bubble.arrowSize.height-k_BOUNDYR_MARGIN - (bubble.textEdgeInsets.left+bubble.textEdgeInsets.right);
            sizeMaxHeight = relateView.bounds.size.height - k_BOUNDYR_MARGIN*2-(bubble.textEdgeInsets.top + bubble.textEdgeInsets.bottom);
        }
            break;
        case HRBubbleArrowDown:
        {
            sizeMaxWidth = relateView.bounds.size.width-k_BOUNDYR_MARGIN*2 - (bubble.textEdgeInsets.left+bubble.textEdgeInsets.right);
            sizeMaxHeight = arrowPoint.y - bubble.arrowSize.height - k_BOUNDYR_MARGIN-(bubble.textEdgeInsets.top + bubble.textEdgeInsets.bottom);
        }
            break;
        default:
        {
            sizeMaxWidth = relateView.bounds.size.width-k_BOUNDYR_MARGIN*2 - (bubble.textEdgeInsets.left+bubble.textEdgeInsets.right);
            sizeMaxHeight = relateView.bounds.size.height - arrowPoint.y - bubble.arrowSize.height - k_BOUNDYR_MARGIN-(bubble.textEdgeInsets.top + bubble.textEdgeInsets.bottom);

        }
            break;
    }
    
    CGFloat closeW = 0.f;
    if (showClose) {
        closeW = bubble.closeButton.frame.size.width + 10;
    }
    
    CGSize textSize = [bubble hr_sizeOfString:bubble.text maxSize:CGSizeMake(sizeMaxWidth, sizeMaxHeight-closeW)];
    CGSize bubbleRectSize = CGSizeMake(textSize.width + closeW +  (bubble.textEdgeInsets.left+bubble.textEdgeInsets.right), textSize.height + (bubble.textEdgeInsets.top+bubble.textEdgeInsets.bottom));
    

    if (showClose) {
//        bubble.textEdgeInsets.right = bubble.textEdgeInsets.right + bubble.closeButton.frame.size.width;
    }
    
    
    
    
    
    
    return bubble;
}

/**
 arrowPoint 箭头指向的点
 */
+ (void)showText:(NSString *)text
          inView:(UIView *)view
     orientation:(HRBubbleArrowOrientation)orientation
      arrowPoint:(CGPoint)arrowPoint
{
    HRBubbleView *bubble = [HRBubbleView showText:text inView:view orientation:orientation arrowPoint:arrowPoint showClose:YES];
    [bubble hr_show];
}

/**
 duration 时间后隐藏
 */
+ (void)showText:(NSString *)text
          inView:(UIView *)view
     orientation:(HRBubbleArrowOrientation)orientation
      arrowPoint:(CGPoint)arrowPoint
        duration:(NSTimeInterval)duration
{
    HRBubbleView *bubble = [HRBubbleView showText:text inView:view orientation:orientation arrowPoint:arrowPoint showClose:YES];
    [bubble hr_showWithDuration:duration];
}

+ (void)showText:(NSString *)text
          inView:(UIView *)view
      arrowPoint:(CGPoint)arrowPoint
{
    return [HRBubbleView showText:text
                           inView:view
                      orientation:HRBubbleArrowUp
                       arrowPoint:arrowPoint];
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {

    //箭头的曲线
    UIBezierPath *arrowPath = [UIBezierPath bezierPath];
    [arrowPath moveToPoint:self.arrowTriangle.top];
    [arrowPath addLineToPoint:self.arrowTriangle.left];
    [arrowPath addLineToPoint:self.arrowTriangle.right];
    [arrowPath addLineToPoint:self.arrowTriangle.top];
    
    UIBezierPath *rectPath = [UIBezierPath bezierPathWithRoundedRect:self.bubbleRect cornerRadius:self.radius];
    
    [self.color setFill];
    [arrowPath fill];
    [rectPath fill];

    [self.text drawInRect:self.textRect
           withAttributes:[self hr_testAttribute]];

    if (self.showCloseButton) {
        self.closeButton.hidden = NO;
        self.closeButton.center = CGPointMake(CGRectGetMaxX(self.bubbleRect)-self.closeButton.frame.size.width/2.0, self.bubbleRect.origin.y+self.closeButton.frame.size.height/2.0);
    }
    else{
        self.closeButton.hidden = YES;
    }
}

- (UIButton *)closeButton
{
    if (!_closeButton) {
        _closeButton = [UIButton buttonWithType:UIButtonTypeSystem];
        _closeButton.backgroundColor = [UIColor whiteColor];
//        [_closeButton setImage:UIImage imageNamed:@"" forState:UIControlStateNormal];
        _closeButton.frame = CGRectMake(0, 0, 20, 20);
        [_closeButton addTarget:self action:@selector(hr_closeAction) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:_closeButton];
    }
    
    return _closeButton;
}

- (void)hr_closeAction{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self hr_dissmiss];
    });
}

- (void)hr_show{
    self.alpha = 0.9;
    [UIView animateWithDuration:0.1
                          delay:0.f
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
            self.alpha = 1.f;
        } completion:^(BOOL finished) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self hr_dissmiss];
            });
        }];
}


- (void)hr_showWithDuration:(NSTimeInterval)duration{
    self.alpha = 0.9;
    [UIView animateWithDuration:duration
                          delay:0.f
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
            self.alpha = 1.f;
        } completion:^(BOOL finished) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self hr_dissmiss];
            });
        }];
}


- (void)hr_dissmiss{
    [UIView animateWithDuration:0.1f
                          delay:0.f
                        options:UIViewAnimationOptionCurveEaseIn
                     animations:^{
            self.alpha = 0.f;
        } completion:^(BOOL finished) {
            [self removeFromSuperview];
        }];
}


- (void)hr_initBubble
{
    self.backgroundColor = [UIColor clearColor];
    self.arrowOrientation = HRBubbleArrowUp;
    self.arrowSize = CGSizeMake(20, 10);
    self.color = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.9];
    self.radius = 8.f;
    self.showCloseButton = YES;
    [self addSubview:self.closeButton];
    self.font = [UIFont systemFontOfSize:12.0];
    self.textColor = [UIColor whiteColor];
    self.textEdgeInsets = UIEdgeInsetsMake(8, 8, 8, 8);
    
    self.arrowTriangle = HRArrowTriangleZero;
    self.bubbleRect = CGRectZero;
    self.textRect = CGRectZero;
}

- (NSDictionary *)hr_testAttribute{
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
    paragraphStyle.lineSpacing = 2.f;
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
    
    return @{
        NSFontAttributeName:self.font,
        NSParagraphStyleAttributeName:paragraphStyle,
        NSForegroundColorAttributeName:self.textColor
    };
}

- (CGSize)hr_sizeOfString:(NSString *)test maxSize:(CGSize)maxSize{
    NSDictionary *attribute = [self hr_testAttribute];
    CGSize size = [self.text boundingRectWithSize:maxSize
                options:NSStringDrawingUsesLineFragmentOrigin
                                       attributes:attribute
                                          context:nil].size;
    return size;
}

- (instancetype)init
{
    if (self = [super init]) {
        [self hr_initBubble];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self hr_initBubble];
    }
    return self;
}

+ (UIWindow *)hr_appWindow
{
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    
    if (window) {
        return window;
    }
    
    if (@available(iOS 13.0, *)) {
        for(UIWindowScene *ws in [UIApplication sharedApplication].connectedScenes){
            if (ws.activationState == UISceneActivationStateForegroundActive) {
                window = ws.windows.firstObject;
                break;
            }
        }
    }else{
        window = [[UIApplication sharedApplication] keyWindow];
    }
    return window;
}


@end
